/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { getScreenType, ScreenBreakpoint } from '../rule/Breakpoint';
import { getCustomRotationInfo, ScreenStatus, VideoDirection } from '../rule/RotationDatabase';
import Orientation, { OrientationType } from '@react-native-oh-tpl/react-native-orientation-locker';
import { SensorUtil } from '../utils/SensorUtil';

export interface Size {
  width: number
  height: number
}

export interface DeviceRotationCallback {
  (orientation: OrientationType): void;
}

export class AdaptiveRotation {
  private static instance: AdaptiveRotation;
  private initialOrientation: OrientationType = OrientationType.UNKNOWN;
  private lastOrientation: OrientationType = OrientationType.UNKNOWN;
  private deviceRotationCallback: DeviceRotationCallback | undefined = undefined;
  private readonly rotation2OrientationTypeArray = [
    OrientationType.PORTRAIT,
    OrientationType["LANDSCAPE-RIGHT"],
    OrientationType["PORTRAIT-UPSIDEDOWN"],
    OrientationType["LANDSCAPE-LEFT"]
  ];

  private constructor() {
  }

  public static getInstance() {
    if (!AdaptiveRotation.instance) {
      AdaptiveRotation.instance = new AdaptiveRotation();
    }
    return AdaptiveRotation.instance;
  }

  // 开启手机旋转监听
  start() {
    SensorUtil.getInstance().addGravityChangeListener((orientation: number) => {
      let orientationType = OrientationType.UNKNOWN;
      if (orientation >= 0 && orientation < this.rotation2OrientationTypeArray.length) {
        orientationType = this.rotation2OrientationTypeArray[orientation];
      }
      if (this.deviceRotationCallback && this.lastOrientation !== orientationType) {
        this.deviceRotationCallback(orientationType);
      }
      this.lastOrientation = orientationType;
    });
    SensorUtil.getInstance().subscribe();
    this.initialOrientation = Orientation.getInitialOrientation();
    this.lastOrientation = this.initialOrientation;
  }

  // 结束手机旋转监听
  stop() {
    SensorUtil.getInstance().unsubscribe();
    SensorUtil.getInstance().removeGravityChangeListener();
    this.initialOrientation = OrientationType.UNKNOWN;
    this.lastOrientation = OrientationType.UNKNOWN;
  }

  // 重置到初始默认旋转方向
  reset() {
    this.setOrientation(this.initialOrientation);
  }

  // 进入全屏自适应旋转
  setOrientationFullScreen(videoSize: Size) {
    let screenBreakpoint: ScreenBreakpoint = getScreenType();
    let videoDirection = videoSize.width > videoSize.height ? VideoDirection.LANDSCAPE : VideoDirection.PORTRAIT;
    let screenStatus = videoSize.width > videoSize.height ? ScreenStatus.LANDSCAPE_FULLSCREEN : ScreenStatus.PORTRAIT_FULLSCREEN;
    let orientations: number[] = getCustomRotationInfo(screenBreakpoint, videoDirection, screenStatus);
    const rotation = SensorUtil.getInstance().getRotation();
    Orientation.lockToOrientation(orientations[rotation]);
  }

  // 进入非全屏自适应旋转
  setOrientationNotFullScreen(videoSize: Size) {
    let screenBreakpoint: ScreenBreakpoint = getScreenType();
    let videoDirection: VideoDirection = videoSize.width > videoSize.height ? VideoDirection.LANDSCAPE : VideoDirection.PORTRAIT;
    let screenStatus = ScreenStatus.NON_FULLSCREEN;
    let orientations: number[] = getCustomRotationInfo(screenBreakpoint, videoDirection, screenStatus);
    const rotation = SensorUtil.getInstance().getRotation();
    Orientation.lockToOrientation(orientations[rotation]);
  }

  // 添加设备旋转监听回调
  addDeviceRotationCallback(callback: DeviceRotationCallback) {
    this.deviceRotationCallback = callback;
  }

  // 移除设备旋转监听回调
  removeDeviceRotationCallback() {
    this.deviceRotationCallback = undefined;
  }

  private setOrientation(orientation: OrientationType) {
    switch (orientation) {
      case 'PORTRAIT':
        Orientation.lockToPortrait();
        break;
      case 'PORTRAIT-UPSIDEDOWN':
        Orientation.lockToPortraitUpsideDown();
        break;
      case 'LANDSCAPE-LEFT':
        Orientation.lockToLandscapeLeft();
        break;
      case 'LANDSCAPE-RIGHT':
        Orientation.lockToLandscapeRight();
        break;
      default:
        console.log('OrientationType is unknown');
    }
  };
}